package agent.test;


import com.alibaba.jvm.sandbox.api.Information;
import com.alibaba.jvm.sandbox.api.LoadCompleted;
import com.alibaba.jvm.sandbox.api.Module;
import com.alibaba.jvm.sandbox.api.ProcessController;
import com.alibaba.jvm.sandbox.api.annotation.Command;
import com.alibaba.jvm.sandbox.api.listener.ext.Advice;
import com.alibaba.jvm.sandbox.api.listener.ext.AdviceListener;
import com.alibaba.jvm.sandbox.api.listener.ext.EventWatchBuilder;
import com.alibaba.jvm.sandbox.api.resource.ModuleEventWatcher;
import org.kohsuke.MetaInfServices;
import profiler.ProfilerExecutor;
import utils.NamedThreadFactory;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * cd agent-module
 *
 * cp target/agent-module-0.0.1-SNAPSHOT-jar-with-dependencies.jar ~/.sandbox-module/
 *
 * cd /Users/jonny/Downloads/sandbox
 *
 * ./sandbox.sh -p 13163 -d 'broken-clock-tinker/repairCheckState'
 *
 */
@MetaInfServices(Module.class)
@Information(id = "broken-clock-tinker")
public class BrokenClockTinkerModule implements Module, LoadCompleted {
    private ScheduledThreadPoolExecutor scheduledThreadPoolExecutor = new ScheduledThreadPoolExecutor(2, new NamedThreadFactory("profiler-thread", true));

    @Resource
    private ModuleEventWatcher moduleEventWatcher;

    @Command("repairCheckState")
    public void repairCheckState() {

        new EventWatchBuilder(moduleEventWatcher)
                .onClass("install.ren.exercise.agent.Clock")
                .onBehavior("checkState")
                .onWatch(new AdviceListener() {

                    /**
                     * 拦截{@code com.taobao.demo.Cprofilerlock#checkState()}方法，当这个方法抛出异常时将会被
                     * AdviceListener#afterThrowing()所拦截
                     */
                    @Override
                    protected void afterThrowing(Advice advice) throws Throwable {

                        // 在此，你可以通过ProcessController来改变原有方法的执行流程
                        // 这里的代码意义是：改变原方法抛出异常的行为，变更为立即返回；void返回值用null表示
                        ProcessController.returnImmediately(null);
                    }
                });

    }

    @Override
    public void loadCompleted() {
        System.out.println("loadCompleted....");
        ProfilerExecutor.initMac();

        scheduledThreadPoolExecutor.schedule(() -> {
            try {
                System.out.println("ProfilerExecutor.getInstance().start()");

                ProfilerExecutor.getInstance().start();
                scheduledThreadPoolExecutor.schedule(() -> {
                    try {
                        System.out.println("ProfilerExecutor.getInstance().stop()");
                        ProfilerExecutor.getInstance().stop();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }, 15000, TimeUnit.MILLISECONDS);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }, 0, TimeUnit.SECONDS);
    }


}
